/***************************************************************************
 *   Copyright (C) 2007 by Marcin Swiechowicz   *
 *   marcin.swiechowicz@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "kdcaudiovideoeditor.h"

#include <kdcaudiostreamgroup.h>
#include <kdcdisc.h>
#include <kdclib.h>

#include <QStringList>
#include <QHeaderView>

#include <KLocale>
#include <kio/job.h>

KDCAudioVideoEditor::KDCAudioVideoEditor( QWidget *parent )
	: QTreeWidget( parent )
{
	setRootIsDecorated( FALSE );
	setAlternatingRowColors( FALSE );
	setColumnCount( 12 );

	QStringList headers;
	headers << "E" << i18n("Type") << i18n("Mode") << i18n("Codec") << i18n("Channels") << i18n("System");
	headers << i18n("Fps") << i18n("Bitrate") << i18n("Ratio") << i18n("Resolution") << i18n("Delay") << i18n("Size");
	setHeaderLabels( headers );
	header()->setDefaultAlignment( Qt::AlignHCenter | Qt::AlignVCenter );

	p_audioCodecDelegate = new KDCAudioCodecDelegate;
	connect( p_audioCodecDelegate, SIGNAL( codecChanged( KDC::AudioCodec ) ), this, SLOT( slotAudioCodecChanged( KDC::AudioCodec ) ) );
	connect( p_audioCodecDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( slotCloseEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );
	p_audioBitrateDelegate = new KDCAudioBitrateDelegate;
	connect( p_audioBitrateDelegate, SIGNAL( bitrateChanged( int ) ), this, SLOT( slotAudioBitrateChanged( int ) ) );
	connect( p_audioBitrateDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( slotCloseEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );
	p_delayDelegate = new KDCAudioDelayDelegate;
	connect( p_delayDelegate, SIGNAL( delayChanged( int ) ), this, SLOT( on_delayChanged( int ) ) );
	connect( p_delayDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( on_closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );
	p_modeDelegate = new KDCStreamModeDelegate;
	connect( p_modeDelegate, SIGNAL( modeChanged( KDC::StreamMode ) ), this, SLOT( slotModeChanged( KDC::StreamMode ) ) );
	connect( p_modeDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( slotCloseEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );
	p_videoCodecDelegate = new KDCVideoCodecDelegate;
	connect( p_videoCodecDelegate, SIGNAL( codecChanged( KDC::VideoCodec ) ), this, SLOT( slotVideoCodecChanged( KDC::VideoCodec ) ) );
	connect( p_videoCodecDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( slotCloseEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );
	p_videoBitrateDelegate = new KDCVideoBitrateDelegate;
	connect( p_videoBitrateDelegate, SIGNAL( bitrateChanged( int ) ), this, SLOT( slotVideoBitrateChanged( int ) ) );
	connect( p_videoBitrateDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( on_closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );
	p_aspectDelegate = new KDCAspectRatioDelegate;
	connect( p_aspectDelegate, SIGNAL( aspectChanged( KDC::AspectRatio ) ), this, SLOT( slotAspectChanged( KDC::AspectRatio ) ) );
	connect( p_aspectDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( slotCloseEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );
	p_formatDelegate = new KDCVideoFormatDelegate;
	connect( p_formatDelegate, SIGNAL( formatChanged( KDC::VideoFormat ) ), this, SLOT( slotFormatChanged( KDC::VideoFormat ) ) );
	connect( p_formatDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( slotCloseEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );
	p_resolutionDelegate = new KDCResolutionDelegate;
	connect( p_resolutionDelegate, SIGNAL( resolutionChanged( int, int ) ), this, SLOT( slotResolutionChanged( int, int ) ) );
	connect( p_resolutionDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( slotCloseEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );
	p_fpsDelegate = new KDCMovieFpsDelegate;
	connect( p_fpsDelegate, SIGNAL( fpsChanged( double ) ), this, SLOT( slotFpsChanged( double ) ) );
	connect( p_fpsDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( slotCloseEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );
	p_channelDelegate = new KDCAudioChannelDelegate;
	connect( p_channelDelegate, SIGNAL( channelChanged( int ) ), this, SLOT( slotChannelChanged( int ) ) );
	connect( p_channelDelegate, SIGNAL( closeEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ), this, SLOT( slotCloseEditor( QWidget *, QAbstractItemDelegate::EndEditHint ) ) );

	connect( this, SIGNAL( itemDoubleClicked( QTreeWidgetItem *, int ) ), this, SLOT( slotOpenEditor( QTreeWidgetItem *, int ) ) );
	connect( this, SIGNAL( currentItemChanged( QTreeWidgetItem *, QTreeWidgetItem * ) ), this, SLOT( slotCurrentItemChanged( QTreeWidgetItem *, QTreeWidgetItem * ) ) );
	connect( this, SIGNAL( itemClicked( QTreeWidgetItem *, int ) ), this, SLOT( slotItemClicked( QTreeWidgetItem * , int ) ) );

	setItemDelegateForColumn( 2, p_modeDelegate );
}

KDCAudioVideoEditor::~KDCAudioVideoEditor()
{
	delete p_audioCodecDelegate;
	delete p_audioBitrateDelegate;
	delete p_delayDelegate;
	delete p_modeDelegate;
	delete p_videoCodecDelegate;
	delete p_videoBitrateDelegate;
	delete p_aspectDelegate;
	delete p_resolutionDelegate;
	delete p_formatDelegate;
	delete p_fpsDelegate;
	delete p_channelDelegate;
}

void KDCAudioVideoEditor::resizeEvent( QResizeEvent *event )
{
	setColumnWidth( 0, 30 );
	setColumnWidth( 1, 50 );
	setColumnWidth( 2, 90 );
	setColumnWidth( 3, 80 );
	setColumnWidth( 4, 75 );
	setColumnWidth( 5, 70 );
	setColumnWidth( 6, 80 );
	setColumnWidth( 7, 105 );
	setColumnWidth( 8, 70 );
	setColumnWidth( 9, 90 );
	setColumnWidth( 10, 70 );
	setColumnWidth( 11, qMax( 0, event->size().width() - 810 ) );
}

void KDCAudioVideoEditor::setCurrentMovie( KDCMovieGroup *movie )
{
	setCurrentMovie( movie->KDCMovieGroup::movie( 0 ) );
}

void KDCAudioVideoEditor::setCurrentMovie( KDCMovie *movie )
{
	if ( movie )
	{
		qDebug( "KDCAudioVideoEditor::setCurrentMovie( %d )", KDCLib::isNull( movie ) );
		QTreeWidgetItem *item;
		clean();
		p_movie = movie;
		connect( p_movie->videoStream(), SIGNAL( settingsChanged() ), this, SLOT( readSettings() ) );
		connect( p_movie, SIGNAL( settingsChanged() ), this, SLOT( readSettings() ) );
		item = new QTreeWidgetItem;
		addTopLevelItem( item );
		int i;
		for ( i=0; i<12; ++i )
			item->setTextAlignment( i, Qt::AlignHCenter | Qt::AlignVCenter );
		KDCAudioStreamGroup *group = p_movie->audioStreamGroup();
		if ( group )
		{
			for( int j=0; j<group->count(); ++j )
			{
				item = new QTreeWidgetItem;
				addTopLevelItem( item );
				connect( group->stream( j ), SIGNAL( settingsChanged() ), this, SLOT( readSettings() ) );
				for ( i=0; i<12; ++i )
					item->setTextAlignment( i, Qt::AlignHCenter | Qt::AlignVCenter );
			}
		}
		readSettings();
	}
}

void KDCAudioVideoEditor::clean()
{
	qDebug( "KDCAudioVideoEditor::clean()::begin" );
	clear();
	if ( p_movie )
	{
		disconnect( p_movie, SIGNAL( settingsChanged() ), this, SLOT( readSettings() ) );
		disconnect( p_movie->videoStream(), SIGNAL( settingsChanged() ), this, SLOT( readSettings() ) );
		KDCAudioStreamGroup *group = p_movie->audioStreamGroup();
		if ( group )
		{
			for( int i=0; i<group->count(); ++i )
				disconnect( group->stream( i ), SIGNAL( settingsChanged() ), this, SLOT( readSettings() ) );
		}
	}
	p_movie = NULL;
	qDebug( "KDCAudioVideoEditor::clean()::end" );
}

void KDCAudioVideoEditor::readSettings()
{
	if ( p_movie )
	{
		qDebug( "KDCAudioVideoEditor::readSettings()::begin" );
		blockSignals( TRUE );
		QTreeWidgetItem *item = topLevelItem( 0 );
		// videoStream
		KDCVideoStream *streamV = p_movie->videoStream();
		item->setText( 1, i18n("Video") );
		item->setText( 2, KDCLib::toString( streamV->mode() ) );
		item->setText( 3, KDCLib::toString( streamV->codec() ) );
		item->setText( 5, KDCLib::toString( p_movie->videoFormat() ) );
		item->setText( 6, QString::number( p_movie->fps() ) );
		item->setText( 7, KDCLib::bitrateAsString( p_movie->videoStream()->bitrate() ) );
		item->setText( 8, KDCLib::toString( streamV->aspectRatio() ) );
		item->setText( 9, QString::number( p_movie->videoStream()->width() ) + "x" + QString::number( p_movie->videoStream()->height() ) );
		item->setText( 11, KIO::convertSizeFromKiB( p_movie->videoStream()->size() ) );

		// audioStreams
		if ( topLevelItemCount() > 1 )
		{
			KDCAudioStreamGroup *group = p_movie->audioStreamGroup();
			{
				KDCAudioStream *audio;
				for( int i=0; i<group->count(); ++i )
				{
					audio = group->stream( i );
					item = topLevelItem( i + 1 );
					if ( audio->isEnabled() )
						item->setCheckState( 0, Qt::Checked );
					else
						item->setCheckState( 0, Qt::Unchecked );
					item->setText( 1, i18n("Audio") );
					item->setText( 2, KDCLib::toString( audio->mode() ) );
					item->setText( 3, KDCLib::toString( audio->codec() ) );
					item->setText( 4, QString::number( audio->channelCount() ) );
					item->setText( 7, KDCLib::bitrateAsString( audio->bitrate() ) );
					item->setText( 10, QString::number( audio->delay() ) );
					item->setText( 11, KIO::convertSizeFromKiB( audio->size() ) );
				}
			}
		}
		blockSignals( FALSE );
		qDebug( "KDCAudioVideoEditor::readSettings()::end" );
	}
}

void KDCAudioVideoEditor::slotOpenEditor( QTreeWidgetItem *item, int column )
{
	if ( indexOfTopLevelItem( item ) == 0 )
	{
		if ( column != 0 && column != 1 && column != 4 && column != 10 && column != 11 )
		{
			// videoStream
			switch ( column )
			{
				case 3:
				{
					setItemDelegateForColumn( 3, p_videoCodecDelegate );
					break;
				}
				case 5:
				{
					setItemDelegateForColumn( 5, p_formatDelegate );
					break;
				}
				case 6:
				{
					setItemDelegateForColumn( 6, p_fpsDelegate );
					break;
				}
				case 7:
				{
					setItemDelegateForColumn( 7, p_videoBitrateDelegate );
					break;
				}
				case 8:
				{
					setItemDelegateForColumn( 8, p_aspectDelegate );
					break;
				}
				case 9:
				{
					setItemDelegateForColumn( 9, p_resolutionDelegate );
					break;
				}
			}
			item->setFlags( item->flags() | Qt::ItemIsEditable );
			editItem( item, column );
		}
	}
	else
	{
		if ( column == 2 || column == 3 || column == 4 || column == 7 || column == 10 )
		{
			// audioStreams
			switch ( column )
			{
				case 3:
				{
					setItemDelegateForColumn( 3, p_audioCodecDelegate );
					break;
				}
				case 4:
				{
					setItemDelegateForColumn( 4, p_channelDelegate );
					break;
				}
				case 7:
				{
					setItemDelegateForColumn( 7, p_audioBitrateDelegate );
					break;
				}
				case 10:
				{
					setItemDelegateForColumn( 10, p_delayDelegate );
					break;
				}
			}
			item->setFlags( item->flags() | Qt::ItemIsEditable );
			editItem( item, column );
		}
	}
}

void KDCAudioVideoEditor::slotAudioBitrateChanged( int val )
{
	p_movie->audioStreamGroup()->stream( indexOfTopLevelItem( currentItem() ) - 1 )->setBitrate( val );
}

void KDCAudioVideoEditor::slotModeChanged( KDC::StreamMode mode )
{
	int index = indexOfTopLevelItem( currentItem() );
	if ( index == 0 )
		p_movie->videoStream()->setMode( mode );
	else
		p_movie->audioStreamGroup()->stream( index - 1 )->setMode( mode );
}

void KDCAudioVideoEditor::slotDelayChanged( int val )
{
	p_movie->audioStreamGroup()->stream( indexOfTopLevelItem( currentItem() ) - 1 )->setDelay( val );
}

void KDCAudioVideoEditor::slotAudioCodecChanged( KDC::AudioCodec codec )
{
	p_movie->audioStreamGroup()->stream( indexOfTopLevelItem( currentItem() ) - 1 )->setCodec( codec );
}

void KDCAudioVideoEditor::slotVideoBitrateChanged( int val )
{
	p_movie->videoStream()->setBitrate( val );
}

void KDCAudioVideoEditor::slotAspectChanged( KDC::AspectRatio ar )
{
	p_movie->videoStream()->setAspectRatio( ar );
}

void KDCAudioVideoEditor::slotVideoCodecChanged( KDC::VideoCodec codec )
{
	p_movie->videoStream()->setCodec( codec );
}

void KDCAudioVideoEditor::slotFpsChanged( double fps )
{
	p_movie->setFps( fps );
}

void KDCAudioVideoEditor::slotChannelChanged( int count )
{
	p_movie->audioStreamGroup()->stream( indexOfTopLevelItem( currentItem() ) - 1 )->setChannelCount( count );
}

void KDCAudioVideoEditor::slotFormatChanged( KDC::VideoFormat format )
{
	if ( format != p_movie->videoFormat() )
		p_movie->setVideoFormat( format );
}

void KDCAudioVideoEditor::slotResolutionChanged( int width, int height )
{
	p_movie->videoStream()->setResolution( width, height );
}

void KDCAudioVideoEditor::slotCurrentItemChanged( QTreeWidgetItem *current, QTreeWidgetItem *previous )
{
	Q_UNUSED( previous );
	if ( current && p_movie )
	{
		int index = indexOfTopLevelItem( current );
		if ( index == 0 )
		{
			p_videoCodecDelegate->setCurrentData( p_movie );
			p_videoBitrateDelegate->setCurrentData( p_movie );
			p_modeDelegate->setCurrentVideoData( p_movie );
			p_resolutionDelegate->setCurrentData( p_movie );
			p_formatDelegate->setCurrentData( p_movie->videoFormat() );
			p_aspectDelegate->setCurrentData( p_movie );
			p_fpsDelegate->setCurrentData( p_movie );
		}
		else
		{
			p_audioCodecDelegate->setCurrentData( p_movie, index - 1 );
			p_audioBitrateDelegate->setCurrentData( p_movie, index - 1 );
			p_modeDelegate->setCurrentAudioData( p_movie, index - 1 );
			p_channelDelegate->setCurrentData( p_movie, index - 1 );
			p_delayDelegate->setCurrentData( p_movie, index - 1 );
		}
	}
}

void KDCAudioVideoEditor::slotItemClicked( QTreeWidgetItem *item, int column )
{
	int index = indexOfTopLevelItem( item );
	if ( p_movie && column == 0 && index > 0 )
	{
		KDCAudioStream *audio = p_movie->audioStreamGroup()->stream( index - 1 );
		audio->setEnabled( item->checkState( 0 ) );
		audio->refresh();
	}
}

void KDCAudioVideoEditor::slotCloseEditor( QWidget *w, QAbstractItemDelegate::EndEditHint h )
{
	Q_UNUSED( w );
	Q_UNUSED( h );
	if ( currentItem() )
		currentItem()->setFlags( Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
}
